﻿/******************************************************
* author :  cwj
* email  :  chenwenji_360@live.com 
* history:  created by cwj 2015/7/17 13:16:15 
* clrversion :4.0.30319.18444
******************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace System.Linq
{
    /// <summary>
    /// 分页显示
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class PageList<TEntity> : IPageList<TEntity>,INotifyPropertyChanged
    {
        private List<TEntity> Value { get; set; }
        #region 构造方法
        ///// <summary>
        ///// 无参数构造函数，用于创建
        ///// </summary>
        //public PageList()
        //{
        //}

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="source">源数据</param>
        /// <param name="index">当前页面的页数索引</param>
        /// <param name="pageSize">页面容量</param>
        /// <param name="totalCount">总数，默认为空值</param>
        public PageList(IEnumerable<TEntity> source, int index, int pageSize, int? totalCount = null)
            : this(source.AsQueryable(), index, pageSize, totalCount)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="source">源数据</param>
        /// <param name="index">当前页面的索引</param>
        /// <param name="pageSize">页面容量</param>
        /// <param name="totalCount">数据总数，默认为空值</param>
        public PageList(IQueryable<TEntity> source, int index, int pageSize, int? totalCount = null)
        {
            if (index < 0)
                throw new ArgumentOutOfRangeException("index", "索引值不能小于0");
            if (pageSize < 1)
                throw new ArgumentOutOfRangeException("pageSize", "页容量必须大于1");

            Value = new List<TEntity>();

            if (source == null)
                source = new List<TEntity>().AsQueryable();

            var realTotalCount = source.Count();

            PageSize = pageSize;
            PageIndex = index;
            TotalItemCount = totalCount.HasValue ? totalCount.Value : realTotalCount;
            PageCount = TotalItemCount > 0 ? (int)Math.Ceiling(TotalItemCount / (double)PageSize) : 0;

            HasPreviousPage = (PageIndex > 0);
            HasNextPage = (PageIndex < (PageCount - 1));
            IsFirstPage = (PageIndex <= 0);
            IsLastPage = (PageIndex >= (PageCount - 1));

            ItemStart = PageIndex * PageSize + 1;
            ItemEnd = Math.Min(PageIndex * PageSize + PageSize, TotalItemCount);

            if (TotalItemCount <= 0)
                return;

            var realTotalPages = (int)Math.Ceiling(realTotalCount / (double)PageSize);

            try
            {
                if (realTotalCount < TotalItemCount && realTotalPages <= PageIndex)
                    Value.AddRange(source.Skip((realTotalPages - 1) * PageSize).Take(PageSize));
                else
                    Value.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
            }
            catch (NotSupportedException ex)
            {
                throw new NotSupportedException("调用ToPageList前必须调用排序", ex);
            }
        }
        #endregion

        #region 接口
        private int _pageCount;
        /// <summary>
        /// 页面数
        /// </summary>
        public int PageCount
        {
            get { return _pageCount;}
            set
            {
                _pageCount = value; this.OnPropertyChanged("PageCount");
            }
        }
        private int _totalItemCount;
        /// <summary>
        /// 总数据数
        /// </summary>
        public int TotalItemCount
        {
            get { return _totalItemCount; }
            set { _totalItemCount = value; this.OnPropertyChanged("TotalItemCount"); }
        }
        private int _pageIndex;
        /// <summary>
        /// 当前页面索引
        /// </summary>
        public int PageIndex
        {
            get { return _pageIndex; }
            set { _pageIndex = value; this.OnPropertyChanged("PageIndex"); }
        }
        private int _pageNumber;
        /// <summary>
        /// 当前数据拥有的页面数
        /// </summary>
        public int PageNumber
        {
            get
            {
                return _pageCount == 0 ? 0 : _pageIndex + 1;
            }
            set
            {
            }
        }
        private int _pageSize;
        /// <summary>
        /// 当前页面容量
        /// </summary>
        public int PageSize
        {
            get { return _pageSize; }
            set { _pageSize = value; this.OnPropertyChanged("PageSize"); }
        }
        private bool _hasPreviousPage;
        /// <summary>
        /// 是否拥有前页
        /// </summary>
        public bool HasPreviousPage
        {
            get { return _hasPreviousPage; }
            set { _hasPreviousPage = value; this.OnPropertyChanged("HasPreviousPage"); }
        }
        private bool _hasNextPage;
        /// <summary>
        /// 是否拥有下一页
        /// </summary>
        public bool HasNextPage
        {
            get { return _hasNextPage; }
            set { _hasNextPage = value; this.OnPropertyChanged("HasNextPage"); }
        }
        private bool _isFirstPage;
        /// <summary>
        /// 是否首页
        /// </summary>
        public bool IsFirstPage
        {
            get { return _isFirstPage; }
            set { _isFirstPage = value; this.OnPropertyChanged("IsFirstPage"); }
        }
        private bool _isLastPage;
        /// <summary>
        /// 是否最后一页
        /// </summary>
        public bool IsLastPage
        {
            get { return _isLastPage; }
            set { _isLastPage = value; this.OnPropertyChanged("IsLastPage"); }
        }
        private int _itemStart;
        /// <summary>
        /// 数据起始位置
        /// </summary>
        public int ItemStart
        {
            get { return _itemStart; }
            set { _itemStart = value; this.OnPropertyChanged("ItemStart"); }
        }
        private int _itemEnd;
        /// <summary>
        /// 数据结束位置
        /// </summary>
        public int ItemEnd
        {
            get { return _itemEnd; }
            set { _itemEnd = value; this.OnPropertyChanged("ItemEnd"); }
        }
        #endregion

        public IEnumerator<TEntity> GetEnumerator()
        {
            return this.Value.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.Value.GetEnumerator();
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
